const express = require("express");
const fs = require("fs");
const path = require("path")
const axios = require("axios");

const app = express();

app.use(express.json())
app.use(express.urlencoded({ extended: true }))

// 设置跨域访问
app.use((req, res, next) => {
  // 允许的域地址，可以根据实际需要修改
  res.header('Access-Control-Allow-Origin', '*');
  // 允许的方法
  res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
  // 允许的头信息字段
  res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With');
 
  // 处理预请求的OPTIONS
  if (req.method === 'OPTIONS') {
    res.sendStatus(200);
  } else {
    next();
  }
});

app.get("/", (req, res) => {
  // writeImageFile()
  console.log(path.basename(new URL('https://cbu01.alicdn.com/img/ibank/O1CN01lQz7fq1t7BPmDJhuZ_!!3446845854-0-cib.jpg?__r__=1685903978122').pathname));
  res.send("请求完成")
})

// 记录当前导出图片文件夹的序号
let dirIndex = 1;

/**
 * 查询设置接口
 */
app.get("/getSetup", (req, res) => {
  fs.readFile(path.resolve(__dirname, "./config.txt"), (err, data) => {
    if (err) {
      return res.json({
        code: 500,
        message: "获取失败"
      })
    }
    const config = configParse(data.toString());

    return res.json({
      code: 200,
      message: "获取成功",
      data: {
        ...config,
        root: config.root || ""
      }
    })
  });
})

/**
 * 保存设置接口
 */
app.post("/saveSetup", (req, res) => {
  const { body } = req;

  console.log(body);

  if (body.subDirs && !Array.isArray(body.subDirs)) {
    return res.json({
      code: 500,
      message: "【subDirs】应该是一个 Array 类型"
    })
  }

  let {
    dirRootPath,  // 根目录
    root, // 导出目录
    subDirs = []  // 子目录
  } = body;
  console.log(subDirs);
  if (!dirRootPath.trim()) {
    return res.json({
      code: 500,
      message: "根目录不能为空"
    })
  }

  let config = `dirRootPath=${dirRootPath}\r\n` +
    `root=${root}\r\n` + 
    `subDirs=${JSON.stringify(subDirs)}`;
    
  try {
    fs.writeFileSync(path.resolve(__dirname, "./config.txt"), config);
    res.json({
      code: 500,
      message: "保存成功"
    })
    init()
  } catch (error) {
    res.json({
      code: 500,
      message: "保存失败"
    })
  }
})

/**
 * 保存图片接口
 */
app.post("/images", async (req, res) => {
  const { body } = req;

  const { images, webUrl } = body;

  const configBuffer = fs.readFileSync(path.resolve(__dirname, "./config.txt"));
  const config = configParse(configBuffer.toString())

  // 系统根路径
  const { root: sysRoot } = path.parse(__dirname);
  // 图片集合的根路径
  const dirRootPath = path.resolve(sysRoot, './' + config.dirRootPath)
  // 图片存放的根路径
  const imageRoot = path.resolve(dirRootPath, `./${config.root}-${dirIndexParse(dirIndex++)}`)

  // 导出图片状态
  let exportImageStatus = true
  
  console.log("创建图片根目录...");
  // 创建图片根目录
  await createDir(imageRoot).catch((err) => {
    console.log("创建图片根目录失败", err);
  })

  let subDirPath = []

  // 创建子目录文件夹
  if (config.subDirs && config.subDirs.length) {
    console.log("创建子目录文件夹...");
    subDirPath = config.subDirs.map(item => {
      return path.resolve(imageRoot, './' + item.dirname)
    })
    exportImageStatus = await createDir(subDirPath).then(() => true).catch(() => false)
  }
  
  if (!exportImageStatus) {
    fs.rmdir(imageRoot, {recursive: true}, (err) => {
      console.log(err);
    })

    // 更新文件夹序号
    dirIndex--;

    return res.json({
      code: 500,
      message: "图片导出失败"
    })
  }

  console.log("开始写入文件");
  
  if (subDirPath.length) {
    for (let i = 0; i < subDirPath.length; i++) {
      const { base } = path.parse(subDirPath[i])
      await writeImageFile(images[base], subDirPath[i]).catch(err => false);
    }
  } else {
    await writeImageFile(images["全部"], imageRoot).catch(err => false);
  }

  console.log("文件写入完成");

  // 生成地址存放文件
  if (exportImageStatus) {
    try {
      fs.writeFileSync(`${imageRoot}\\地址.txt`, webUrl)
    } catch (error) {
      exportImageStatus = false
    }
  }

  if (!exportImageStatus) {
    fs.rmdir(imageRoot, {recursive: true}, (err) => {
      console.log(err);
    })

    dirIndex--;

    return res.json({
      code: 500,
      message: "图片导出失败"
    })
  }

  res.send({
    code: 200,
    message: "图片导出成功"
  })
})

app.all("*", (req, res) => {
  res.send("404 Not Found")
})

/**
 * 写入图片文件
 * @param {Array<string>} images 需要写入的文件
 * @param {string} dir 文件存放的路径
 */
function writeImageFile(images, dir) {
  return new Promise((resolve, reject) => {

    Promise.all(images.map(url => {
      return axios({
        url,
        method: "GET",
        responseType: "stream"
      })
        .then(res => {
          return {data: res.data, url}
        })
        .catch(err => {
          console.log("文件下载异常");
          return err;
        })
    }))
      .then(results => {
        try {
          for (let index = 0; index < results.length; index++) {
            const result = results[index];
            try {
              if (result.url.includes("base64")) {
                const imageBuffer = Buffer.from(result.url.split(';base64,').pop(), 'base64');
                fs.writeFileSync(`${dir}\\${dirIndexParse(index + 1)}.png`, imageBuffer);
              } else {
                const filename = path.basename(new URL(result.url).pathname)
                const writeStream = fs.createWriteStream(`${dir}\\${dirIndexParse(index + 1)}-${filename}`)
                writeStream.on("error", () => {
                  console.log("数据写入异常位置>>", index, "异常数据>>", `${dir}\\${dirIndexParse(index + 1)}-${filename}`);
                })
                result.data.pipe(writeStream)
              }
            } catch (error) {
              
            }
          }
          resolve(true)
        } catch (error) {
          console.log(error);
          reject(false)
        }
      }).catch(err => {
        console.log(err);
        reject(false)
      })
  })
}

/**
 * 创建文件夹
 * @param {string | Array<string>} dirPath 文件夹的路径
 */
function createDir(dirPath) {
  console.log("创建的文件夹地址",dirPath);
  return new Promise((resolve, reject) => {
    if (Array.isArray(dirPath)) {
      Promise.allSettled(dirPath.map(item => {
        return createDir(item)
      }))
        .then((results) => {
          if (results.filter(item => item.status === 'fulfilled').length === dirPath.length) {
            resolve(true)
          } else reject(false);
        })
        .catch(() => reject(false))
    } else {
      fs.mkdir(dirPath, (err) => {
        if (err) {
          console.log(err);
          reject(false)
          return
        }
        resolve(true)
      })
    }
  })
}

/**
 * 
 * @param {number} index 文件夹序号补零
 * @returns 
 */
function dirIndexParse(index) {
  if (index < 10) return `0${index}`;
  return index
}

/**
 * 配置内容格式化
 * @param {string} config 配置文件内容
 * @returns 转化为key:value形式的配置对象
 */
function configParse(config) {
  const configs = config.split("\r\n");

  let obj = {}
  configs.map(item => {
    const [key, value] = item.split('=')
    try {
      const parseStr = JSON.parse(value)
      obj[key] = parseStr
    } catch (error) {
      obj[key] = value
    }
  })  

  return obj
}


function getConfigContent() {
  let config;
  try {
    const configBuffer = fs.readFileSync(path.resolve(__dirname, "./config.txt"));
    config = configParse(configBuffer.toString())
  } catch (error) {
    fs.writeFileSync(path.resolve(__dirname, "./config.txt"), 'dirRootPath=\r\nroot=\r\nsubDirs=')
    config = {
      dirRootPath: "",
      root: "",
      subDirs: [],
    };
  }
  return config
}

function initDirIndex(config) {
  if (config.root) {
    const lastIndex = config.root.lastIndexOf("-")
    dirIndex = Number(config.root.substring(lastIndex + 1)) || 1
  } else {
    dirIndex = 1
  }
  console.log('dirIndex',dirIndex);
}

/**
 * 初始化文件夹序号
 */
function init() {
  const config = getConfigContent()
  if(!config.dirRootPath) return;
  const { root } = path.parse(__dirname)
  const dirRootPath = path.resolve(root, './' + config.dirRootPath)
  try {
    const dirs = fs.readdirSync(dirRootPath)
    let count = 1;
    console.log(dirs);
    dirs.forEach(item => {
      if (fs.statSync(path.resolve(dirRootPath, './' + item)).isDirectory() && item.includes(config.root)) {
        count++;
      }
    })
    dirIndex = count
  } catch (error) {
    console.log(error);
  }
  console.log('dirIndex',dirIndex);
}

app.listen(3000, () => {
  init()
  console.log('http://127.0.0.1:3000');
})